/*
 * Copyright (c) 2017. Visionet and/or its affiliates. All right reserved.
 * VISIONET PROPRIETARY/CONFIDENTIAL.
 */
package com.visionet.jumper.core.support.jpa;

import com.visionet.jumper.core.domain.bean.Page;
import com.visionet.jumper.core.exception.runtime.FrameworkException;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.orm.jpa.SharedEntityManagerCreator;
import org.springframework.util.Assert;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import java.awt.peer.FramePeer;
import java.util.List;
import java.util.Map;

/**
 * @author TC.Ubuntu
 * @since 2017/12/1.
 * 复杂查询辅助类
 */
@SuppressWarnings("unchecked")
public abstract class CommonRepository {

	private static EntityManager entityManager;

	private static void setEntityManager(EntityManagerFactory entityManagerFactory) {
		entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
	}

	private EntityManager getEntityManager() {
		Assert.notNull(entityManager, "entityManager has not been initialized yet,"
				+ "please see [com.visionet.jumper.core.support.jpa.RepositoryHelper#setEntityManagerFactory]");
		return entityManager;
	}

	private Query setParameter(Query query, Map<String, Object> params) {
		if(null != params) {
			for(String paramName : params.keySet()) {
				query.setParameter(paramName, params.get(paramName));
			}
		}
		return query;
	}

	public <T> T findOne(String sqlName, Map<String, Object> params, Class<T> returnType) {
		Query query = getEntityManager().createNativeQuery(SqlReaderFactory.getSqlResource(params, sqlName));
		query = setParameter(query, params);
		query.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(returnType));
		return (T) query.getSingleResult();
	}


	/**
	 * 查询集合
	 * @param sqlName 查询sql
	 * @param params 参数map
	 * @param returnType 返回对象类型
	 * @return 结果集
	 */
	public <T> List<T> findAll(String sqlName, Map<String, Object> params, Class<T> returnType) {
		Assert.notNull(returnType, "query result for return type can not be null");
		Query query = getEntityManager().createNativeQuery(SqlReaderFactory.getSqlResource(params, sqlName));
		query = setParameter(query, params);
		return (List<T>) query.unwrap(SQLQuery.class)
				.setResultTransformer(Transformers.aliasToBean(returnType))
				.list();
	}

	/**
	 * 分页查询集合
	 * @param sqlName 查询sql的名称
	 * @param params 参数map
	 * @param page 分页条件，若为空，则按分页对象初始化状态查询
	 * @return 分页结果集
	 */
	public Page findAllForPage(String sqlName, Map<String, Object> params, Page page) {
		Query query = getEntityManager().createNativeQuery(SqlReaderFactory.getSqlResource(params, sqlName));
		query = setParameter(query, params);
		if(null == page) {
			page = new Page();
			query.setFirstResult(0);
			query.setMaxResults(page.getPageSize());
		} else {
			query.setFirstResult((page.getCurPage()) * page.getPageSize());
			query.setMaxResults(page.getPageSize());
		}
		page.setRows(query.unwrap(SQLQuery.class).list());
		page.setTotal((int) count(sqlName, params));
		return page;
	}

	/**
	 * 获取查询总数
	 * @param sqlName 查询sql
	 * @param params 参数map
	 * @return 结果集总数
	 */
	public long count(String sqlName, Map<String, Object> params) {
		Query query = getEntityManager().createNativeQuery(SqlReaderFactory.getSqlResource(params, sqlName));
		query = setParameter(query, params);
		return (Long) query.getSingleResult();
	}
}
